namespace EFS.EventLog.Writers
{
	public sealed class Email
	{
		// synk
		private object syncAccess = new object();

		// last failed on
		private System.DateTime? lastFailed = null;

		/// Property Instance (singleton): Get
		public static Email Instance { get; private set; }

		/// <summary>
		/// Static constructor to init local instance
		/// </summary>
		static Email()
		{
			Instance = new Email();
		}

		/// <summary>
		/// Contructor
		/// </summary>
		private Email()
		{
		}

		/// Send email
		/// DO NOT LOG ANYTHING OR IT COULD CREATE AN INFINITE LOOP
		internal void Write(System.String message)
		{
			// check
			if (null == message || !EFS.Common.Verify.String(EFS.EventLog.Config.Log.EmailLog.EmailAddressRecipient))
			{
				return;
			}

			// check if failed in last h
			if (lastFailed.HasValue)
			{
				if (lastFailed.Value > System.DateTime.Now.AddHours(-1))
				{
					// write
					WriteEmailError(System.String.Format("Email log failed within 1h, Email log will resume in {0} minutes.", (System.DateTime.Now.AddHours(1) - lastFailed.Value).Minutes));

					// done here
					return;
				}

				// reset last failed
				lastFailed = null;
			}

			try
			{
				// create the message
				System.Text.StringBuilder sbMessage = new System.Text.StringBuilder();
				sbMessage.AppendFormat("{1}{0}{0}{2}{0}{0}{3}",
					System.Environment.NewLine,
					FQDN,
					System.DateTime.Now.ToString(),
					message);

				// create mail message
				System.Net.Mail.MailMessage mailMessage = new System.Net.Mail.MailMessage();

				// sender
				mailMessage.From = new System.Net.Mail.MailAddress(EFS.EventLog.Config.Log.EmailLog.EmailAddressSender);

				// recipient
				mailMessage.To.Add(new System.Net.Mail.MailAddress(EFS.EventLog.Config.Log.EmailLog.EmailAddressRecipient));

				// set subject
				mailMessage.Subject = "EFS.Eventlog";

				// set body
				//mailMessage.Body = EFS.Common.Functions.GetHTMLFormated(sbMessage.ToString());
				mailMessage.Body = sbMessage.ToString();

				// set body type
				mailMessage.IsBodyHtml = false;

				// smtp client
				System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient(EFS.EventLog.Config.Log.EmailLog.EmailServer);

				// ssl
				//smtpClient.EnableSsl = true;
				smtpClient.EnableSsl = false;

				// send via network
				smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;

				// send mail
				smtpClient.Send(mailMessage);
			}
			catch (System.Exception ex)
			{
				// keep last faield
				lastFailed = System.DateTime.Now;
				
				// write email erro log
				WriteEmailError(EFS.EventLog.EventDescriptor.Exception(ex, null));
			}
		}

		/// <summary>
		/// full qualify domain name
		/// </summary>
		private System.String fqdn = null;
		private System.String FQDN
		{
			get
			{
				if (null == fqdn)
				{
					var ipProperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
					EFS.Common.Verify.Reference(ipProperties, "ipProperties");

					// set
					fqdn = string.Format("{0}.{1}", ipProperties.HostName, ipProperties.DomainName);
				}

				return fqdn;
			}
		}

		// Log entry
		private void WriteEmailError(System.String message)
		{
			// ~ commented for performance ~  EFS.EventLog.Log.LogExtended("Entering lock", new System.Diagnostics.StackTrace());
			lock (syncAccess)
			{
				try
				{
					// email log
					System.IO.StreamWriter sw = new System.IO.StreamWriter(EmailLogFilePath, true);

					// write
					sw.WriteLine(message);

					// close
					sw.Close();
				}
				catch (System.Exception e)
				{
					System.Diagnostics.Debug.WriteLine(e);
				}
			}
		}

		/// <summary>
		/// send email exception log file
		/// </summary>
		public static System.String EmailLogFilePath
		{
			get
			{
				// log email send exception in different file
				return EFS.EventLog.Config.Log.FileLog.FilePath + "send.email.exception" + ".txt";
			}
		}
	}
}